package com.android.baseconfig.data.http.okhttp;

import android.os.Environment;
import android.util.Log;

import com.android.baseconfig.base.BaseSharedPreferences;
import com.android.baseconfig.common.config.HttpConstant;
import com.android.baseconfig.common.helper.LoggerInterceptor;
import com.android.baseconfig.common.utils.StringUtils;
import com.android.baseconfig.data.http.AppNetDelegate;
import com.android.baseconfig.data.http.okhttp.interceptor.HeTLoggerInterceptor;
import com.android.baseconfig.data.http.okhttp.interceptor.HeTNetworkLoadingInterceptor;
import com.android.baseconfig.data.http.okhttp.interceptor.TokenInterceptor;
import com.android.baseconfig.data.http.okhttp.listener.NetworkLoadingListener;
import com.android.baseconfig.data.http.okhttp.util.NetworkUtil;
import com.android.baseconfig.data.http.okhttp.util.TimeOut;
import com.android.baseconfig.data.http.okhttp.util.XDns;
import com.android.baseconfig.data.http.ssl.HttpsUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class OkHttpManager {
    public static String TAG = "Ok";
    private static OkHttpClient client;
    private static InputStream[] certificates;
    private static HeTNetworkLoadingInterceptor networkInterceptor = null;
    private static LoggerInterceptor loggerInterceptor = null;
    private static boolean showLog = false;

    private OkHttpManager() {
    }

    public static OkHttpClient.Builder creater(HeTNetworkLoadingInterceptor listener, InputStream... cer) {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(cer, null, null);
        return new OkHttpClient.Builder()
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier())
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
    }

    public static OkHttpClient.Builder create(InputStream... cer) {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(cer, null, null);
        return newClient()
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier())
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
    }

    public static String time() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);// HH:mm:ss
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        //获取当前时间
        Date date = new Date(System.currentTimeMillis());
        return simpleDateFormat.format(date);
    }

    public static void setLogger(boolean showLog) {
        OkHttpManager.showLog = showLog;
        if (loggerInterceptor != null) {
            loggerInterceptor.setShowLog(showLog);
        }
    }

    public static OkHttpClient.Builder newClient() {

        /*
         * 设置请求头
         */
        Interceptor headerInterceptor = chain -> {
            String token = BaseSharedPreferences.getString(AppNetDelegate.getAppContext(), HttpConstant.TOKEN);
            // Logc.e("newClient: token: " + token);
            String time = time();
            String md5 = StringUtils.md5("9e16b3a5-aa6d-4904-a65f-d8796b5bf5dd" + time
                    + "c32a4d61-b833-4194-b5fa-6dc8506c6565");
            return chain.proceed(chain.request()
                    .newBuilder()
                    .addHeader("Content-Type", "application/json; charset=UTF-8")
                    .addHeader("token-header", "Authorization")
                    .addHeader("X-Supor-App-Id", "9e16b3a5-aa6d-4904-a65f-d8796b5bf5dd")
                    .addHeader("X-Supor-Timestamp", time)
                    .addHeader("X-Supor-Signature", md5)
                    .addHeader("X-Supor-Signature-Debug", "true")
                    .addHeader("sign-test", "true")
                    .addHeader(HttpConstant.TOKEN, token)
                    .build());
        };

        HeTLoggerInterceptor hetLoggerInterceptor = new HeTLoggerInterceptor(TAG, true);
        loggerInterceptor = new LoggerInterceptor(TAG, showLog);

        int maxCacheSize = 100 * 1024 * 1024;
        File cFile;
        if (AppNetDelegate.getAppContext() != null && AppNetDelegate.getAppContext().getCacheDir() != null) {
            cFile = AppNetDelegate.getAppContext().getCacheDir();
        } else {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath();//获取跟目录
            cFile = new File(path + "/het");
        }
        Cache cache = new Cache(cFile, maxCacheSize);

        // add your other interceptors …
        // add logging as last interceptor
        OkHttpClient.Builder newclient = new OkHttpClient.Builder()
                .readTimeout(TimeOut.READ, TimeUnit.SECONDS)
                .connectTimeout(TimeOut.CONNECT, TimeUnit.SECONDS)
                .writeTimeout(TimeOut.WRITE, TimeUnit.SECONDS)
                .dns(new XDns(TimeOut.READ, TimeUnit.SECONDS))
                .addNetworkInterceptor(new HttpCacheInterceptor())
                .addInterceptor(headerInterceptor)
                .addInterceptor(new TokenInterceptor())
                .addInterceptor(loggerInterceptor)
                // .addInterceptor(new DynamicTimeoutInterceptor())
                // .addInterceptor(new HeTInterceptor())
                // .authenticator(new TokenAuthenticator())
                .cache(cache);
        return newclient;
    }

    public static OkHttpClient getClient() {
        if (client == null) {
            client = newClient().build();
        }
        return client;
    }

    public static void addNetworkInterceptor(Interceptor interceptor) {
        client = getClient().newBuilder()
                .addNetworkInterceptor(interceptor)
                .build();
    }

    public static void addInterceptor(Interceptor interceptor) {
        client = getClient().newBuilder()
                .addInterceptor(interceptor)
                .build();
    }

    public static void addNetworkLoadingListener(NetworkLoadingListener listener) {
        OkHttpClient.Builder builder = getClient().newBuilder();
        List<Interceptor> interceptors = builder.interceptors();
        Iterator<Interceptor> it = interceptors.iterator();
        boolean hasNetworkLoadingListener = false;
        while (it.hasNext()) {
            Interceptor interceptor = it.next();
            if (interceptor != null) {
                if (interceptor instanceof HeTNetworkLoadingInterceptor) {
                    hasNetworkLoadingListener = true;
                    HeTNetworkLoadingInterceptor loadingInterceptor = (HeTNetworkLoadingInterceptor) interceptor;
                    loadingInterceptor.setLoadingListener(listener);
                    break;
                }
            }
        }
        if (!hasNetworkLoadingListener) {
            builder.addInterceptor(new HeTNetworkLoadingInterceptor(listener));
        }
        client = builder.build();
    }


    /**
     * 设置整数，不传参数表示信任全部证书
     *
     * @param cer
     */
    public static void setCertificates(InputStream... cer) {
        certificates = cer;
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(cer, null, null);
        client = getClient().newBuilder()
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier())
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .build();
    }

    public static OkHttpClient newOkHttp(InputStream... cer) {
        certificates = cer;
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(cer, null, null);
        return newClient()
                .hostnameVerifier(new HttpsUtils.UnSafeHostnameVerifier())
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .build();
    }

    /**
     * for https mutual authentication
     *
     * @param certificates
     * @param bksFile
     * @param password
     */
    public static void setCertificates(InputStream[] certificates, InputStream bksFile, String password) {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(certificates, bksFile, password);
        client = getClient()
                .newBuilder()
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .build();
    }

    public static void setConnectTimeout(long timeout) {
        client = getClient()
                .newBuilder()
                .connectTimeout(timeout, TimeUnit.MILLISECONDS)
                .build();
    }

    public static void setReadTimeout(long timeout) {
        client = getClient()
                .newBuilder()
                .readTimeout(timeout, TimeUnit.MILLISECONDS)
                .build();
    }

    public static void setWriteTimeout(long timeout) {
        client = getClient()
                .newBuilder()
                .writeTimeout(timeout, TimeUnit.MILLISECONDS)
                .build();
    }

    public static void setNoProxy() {
        client = getClient()
                .newBuilder()
                .proxy(Proxy.NO_PROXY)
                .build();
    }

    static class HttpCacheInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetworkUtil.isNetworkAvailable(AppNetDelegate.getAppContext())) {
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
                Log.d("Okhttp", "no network");
            }

            Response originalResponse = chain.proceed(request);
            if (NetworkUtil.isConnected(AppNetDelegate.getAppContext())) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                //                Response.Builder builder = originalResponse.newBuilder();
                //                Response clone = builder.build();
                //                ResponseBody body = clone.body();
                //                System.out.println("uuok.base....:"+body.string());
                String cacheControl = request.cacheControl().toString();
                return originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                        .removeHeader("Pragma")
                        .build();
            }
        }
    }

    public static void release() {
        client = null;
    }

}
